package com.course.web.component.custom;

import com.course.util.DateUtils;
import com.course.web.biz.WebAgendaBiz;
import com.course.web.biz.WebCourseBiz;
import com.course.web.biz.WebStudentBiz;
import com.course.web.component.base.BaseEdit;
import com.course.web.component.base.BaseGrid;
import com.course.web.component.base.BaseList;
import com.course.web.component.base.EditGrid;
import com.course.web.model.AgendaInfoVM;
import com.course.web.model.CourseInfoVM;
import com.course.web.model.StudentVM;
import com.course.web.view.AgendaPlanView;
import com.course.web.view.ClassMarkView;
import com.course.web.view.ClassPlanView;
import com.vaadin.data.Binder;
import com.vaadin.data.converter.StringToIntegerConverter;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.*;
import org.apache.commons.lang3.math.NumberUtils;

import java.time.DayOfWeek;
import java.time.LocalDate;

/**
 * Created by Justin on 2017/6/10.
 */
@SpringComponent
@ViewScope
public class StudentGrid extends EditGrid<StudentVM> {

    private final WebStudentBiz studentBiz;
    private final WebAgendaBiz agendaBiz;
    private final WebCourseBiz courseBiz;
    private final CourseEdit courseEdit;
    private final ChangeEdit changeEdit;

    public StudentGrid(WebStudentBiz studentBiz,
                       WebAgendaBiz agendaBiz,
                       WebCourseBiz courseBiz) {
        super(StudentVM.class);
        this.studentBiz = studentBiz;
        this.agendaBiz = agendaBiz;
        this.courseBiz = courseBiz;
        this.courseEdit = new CourseEdit();
        this.changeEdit = new ChangeEdit();
    }

    @Override
    protected void doInitMenu(Layout menu) {
        Button create = new Button("添加");
        menu.addComponent(create);
        create.addClickListener(event -> createShow());
    }

    @Override
    protected void doInitGrid(BaseGrid<StudentVM> grid) {
        grid.addColumn(StudentVM::getIntro, "描述");
        grid.addColumn(StudentVM::getUsername, "登录ID");
        grid.addColumn(StudentVM::getName, "姓名");
        grid.addColumn(StudentVM::getCourseId, "课程ID");
        grid.addColumn(StudentVM::getScore, "积分");
        grid.addColumn(StudentVM::getExchange, "兑换");
        grid.addButton(this::updateShow, "编辑");
        grid.addButton(this::course, "选课");
        grid.addButton(this::agenda, "排期");
        grid.addButton(this::attend, "排线上课");
        grid.addButton(this::change, "兑换积分");
        grid.addButton(this::remark, "评价翻译");
        grid.addButton(this::delete, "删除");
    }

    @Override
    protected void doInitEdit(BaseEdit<StudentVM> edit) {
        FormLayout form = new FormLayout();
        TextField username = new TextField("用户名");
        TextField password = new TextField("密码");
        TextField name = new TextField("学生姓名");
        TextField link = new TextField("学生PPT");
        TextField audio = new TextField("音频文件");
        TextField intro = new TextField("描述");
        TextField score = new TextField("积分");
        form.addComponent(username);
        form.addComponent(password);
        form.addComponent(name);
        form.addComponent(link);
        form.addComponent(audio);
        form.addComponent(intro);
        form.addComponent(score);
        form.setMargin(false);
        StringToIntegerConverter converter = new StringToIntegerConverter("输入数字");
        Binder<StudentVM> binder = edit.binder();
        binder.bind(username, "username");
        binder.bind(password, "password");
        binder.bind(name, "name");
        binder.bind(link, "link");
        binder.bind(audio, "audio");
        binder.bind(intro, "intro");
        binder.forField(score).withConverter(converter).bind("score");
        edit.initEdit(form);
    }

    @Override
    protected StudentVM doCreate() {
        return new StudentVM();
    }

    @Override
    protected StudentVM doCreate(StudentVM item) {
        return studentBiz.create(item);
    }

    @Override
    protected StudentVM doUpdate(StudentVM item) {
        return studentBiz.update(item);
    }

    @Override
    protected StudentVM doDelete(StudentVM item) {
        return studentBiz.delete(item);
    }

    private void course(StudentVM item) {
        if (item == null) {
            return;
        }

        int studentId = item.getStudentId();
        int courseId = item.getCourseId();
        if (courseId == 0) {
            AgendaInfoVM info = new AgendaInfoVM(studentId);
            info.setLocalDate(DateUtils.toLocalDate(DateUtils.now()));
            courseEdit.show(getUI(), info, item);
        } else {
            AgendaInfoVM info = agendaBiz.loadInfo(studentId, courseId);
            info.setLocalDate(DateUtils.toLocalDate(info.getDate()));
            courseEdit.show(getUI(), info, item);
        }
    }

    private void agenda(StudentVM item) {
        int studentId = item.getStudentId();
        int courseId = item.getCourseId();
        AgendaInfoVM agendaInfo = agendaBiz.loadInfo(studentId, courseId);
        if (agendaInfo != null) {
            getUI().getNavigator().navigateTo(AgendaPlanView.NAME + "/" + agendaInfo.getId());
        }
    }

    private void attend(StudentVM item) {
        int studentId = item.getStudentId();
        getUI().getNavigator().navigateTo(ClassPlanView.NAME + "/" + studentId);
    }

    private void remark(StudentVM item) {
        int studentId = item.getStudentId();
        getUI().getNavigator().navigateTo(ClassMarkView.NAME + "/" + studentId);
    }

    private void change(StudentVM item) {
        if (item == null) {
            return;
        }
        changeEdit.show(getUI(), item);
    }

    public void enter() {
        init(studentBiz.list());
        courseEdit.enter();
    }

    private class CourseEdit extends BaseEdit<AgendaInfoVM> {

        private final BaseList<CourseInfoVM> courseList;
        private final DateField date;

        private StudentVM item;

        CourseEdit() {
            super(AgendaInfoVM.class);
            this.courseList = new BaseList<>();
            this.date = new DateField("上课日期");

            Layout root = new FormLayout();
            root.addComponent(date);
            root.addComponent(courseList);
            initEdit(root);

            courseList.setCaption("选择课程");
            courseList.addColumn(CourseInfoVM::getId, "ID");
            courseList.addColumn(CourseInfoVM::getTitle, "标题");
            courseList.addColumn(CourseInfoVM::getWeeks, "周数");

            Binder<AgendaInfoVM> binder = binder();
            binder.bind(date, "localDate");
            binder.bind(courseList.adapter(), "courseId");
            setHandler(this::save);

            date.addValueChangeListener(event -> {
                LocalDate localDate = event.getValue();
                DayOfWeek dayOfWeek = localDate.getDayOfWeek();
                int weekDay = dayOfWeek.getValue();
                if (weekDay != 1) {
                    date.setValue(localDate.minusDays(weekDay - 1));
                }
            });
        }

        void show(UI ui, AgendaInfoVM info, StudentVM item) {
            this.item = item;
            super.show(ui, info);
        }

        private void save(AgendaInfoVM info) {
            int courseId = info.getCourseId();
            if (courseId == 0) {
                return;
            }
            info.setDate(DateUtils.toDate(info.getLocalDate()));
            if (info.getId() == 0) {
                agendaBiz.createInfo(info);
            } else {
                agendaBiz.updateInfo(info);
            }
            item.setCourseId(courseId);
            update(item);
        }

        void enter() {
            courseList.setItems(courseBiz.listInfo());
        }
    }

    private class ChangeEdit extends BaseEdit<StudentVM> {

        private TextField score;

        ChangeEdit() {
            super(StudentVM.class);
            FormLayout form = new FormLayout();
            score = new TextField("兑换积分");
            form.addComponent(score);
            initEdit(score);

            setHandler(this::exchange);
        }

        @Override
        public void show(UI ui, StudentVM bean) {
            score.setValue("");
            super.show(ui, bean);
        }

        private void exchange(StudentVM item) {
            int value = NumberUtils.toInt(score.getValue());
            item.setExchange(item.getExchange() + value);
            update(item);
        }

    }

}
